package dfbz.com.dao.base;

import dfbz.com.annotation.MyField;
import dfbz.com.annotation.Table;
import dfbz.com.utils.JDBCUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class BaseDao<T> {


    public void add(T t) {

        Class<?> aClass = t.getClass();
        //通过反射拿到注解
        Table table = aClass.getDeclaredAnnotation(Table.class);
        String tableName = null;

        if (table != null) {
            tableName = table.value();
        }

        Field[] fields = aClass.getDeclaredFields();

        StringBuilder sql = new StringBuilder();

        sql.append(" insert into ").append(tableName).append(" values(");

        for (int i = 1; i <=fields.length ; i++) {
            if (i == fields.length){
                sql.append("?").append(")");
            }else {
                sql.append("?").append(",");
            }
        }


        Connection connection = null;//数据库链接
        PreparedStatement statement = null;//sql预处理执行

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql.toString());

            int index = 1;

            for (Field field:fields) {

                //相当于得到javabean的get方法
                String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                Method method = aClass.getDeclaredMethod(methodName);

                //反射添加属性
                statement.setObject(index,method.invoke(t));
                index++;
            }

            statement.execute();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, statement, connection);
        }

    }

    public void del(Object ids,Class<T> aClass) {

//        Class<?> aClass = t.getClass();
        //通过反射拿到注解
        Table table = aClass.getDeclaredAnnotation(Table.class);
        String tableName = null;

        String idName = null;
         if (table != null) {
            tableName = table.value();
            idName = table.key();
        }

//         DELETE FROM "+tableName+" WHERE id in (ids)

        StringBuilder sql = new StringBuilder();

        sql.append(" DELETE FROM ").append(tableName).append(" where ");
        sql.append(idName).append(" in ( ");
        sql.append(ids).append(" ) ");

        System.out.println(sql.toString());


        Connection connection = null;//数据库链接
        PreparedStatement statement = null;//sql预处理执行

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql.toString());

            statement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, statement, connection);
        }
    }

    public T get(Object id, Class<T> aClass) {
        //第一步 通过反射，拿到注解
        Table table = aClass.getDeclaredAnnotation(Table.class);
        String tableName = null;
        String idName = null;
        if (null != table) {
            //注解里面的值 就是表名
            tableName = table.value();
            idName = table.key();
        }
        String sql = "select * from " + tableName + " where " + idName + " = ?";
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        T obj = null;
        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            statement.setObject(1, id);
            resultSet = statement.executeQuery();
            if (resultSet.next()) {
                obj = aClass.newInstance();// Student student = new Student();
                //后面都是用反射去获取Student的字段
                Field[] fields = aClass.getDeclaredFields();
                for (Field field : fields) {
                    String fieldName = field.getName();
                    MyField myField = field.getDeclaredAnnotation(MyField.class);
                    if (null != myField) {
                        //自定义注解写上列名重新赋值给fieldName
                        fieldName = myField.value();
                    }
                    String methodName = "set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                    //通过反射 获取set的方法
                    Method method = aClass.getDeclaredMethod(methodName, field.getType());
                    //通过反射 代理执行 本质上就等同于 student.setXXX(resultSet.getObject("XXX"));
                    method.invoke(obj, resultSet.getObject(fieldName));
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, statement, connection);
        }
        return obj;
    }


    public void edit(T t) {
        String idName = null;
        String idMethodName = null;

        Class<?> aClass = t.getClass();
        //根据注解得到数据库的表名
        Table table = aClass.getDeclaredAnnotation(Table.class);
        String tableName = null;

        Field[] fields = aClass.getDeclaredFields();

        //判断注解是否为空  不为空则用变量接收
        if (table != null) {
            tableName = table.value();
            idName = table.key();
            idMethodName = table.keyName();
        }

        StringBuilder sql = new StringBuilder();
        sql.append(" update ").append(tableName).append(" set ").append(idName).append(" = ?,");
//        String sql = " update  user set username=?,phone=?,adress=? where id=?";
        try {
            for (Field field:fields) {
                String fieldName = field.getName();
                MyField myField = field.getDeclaredAnnotation(MyField.class);

                if(null != myField){
                    //自定义注解写上列名重新赋值给fieldName
                    fieldName = myField.value();
                }

                if(!"id".equals(fieldName)){
                    String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                    //通过反射 获取get的方法
                    Method method = aClass.getDeclaredMethod(methodName);
                    Object obj = method.invoke(t);
                    if(null != obj){
                        sql.append(fieldName).append(" = ?,");
                    }
                }
            }
            sql.delete(sql.lastIndexOf(","),sql.length());
            sql.append(" where ").append(idName).append(" = ?");
            System.out.println(sql.toString());

        }catch (Exception e){
            e.printStackTrace();
        }

        Connection connection = null;//数据库链接
        PreparedStatement statement = null;//sql预处理执行

        try {
            int index = 0;
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql.toString());
            Method method = aClass.getDeclaredMethod(idMethodName);
            Object id = method.invoke(t);
            statement.setObject(++index, id);

            for (Field field : fields) {
                String fieldName = field.getName();
                MyField myField = field.getDeclaredAnnotation(MyField.class);
                if(null != myField){
                    //自定义注解写上列名重新赋值给fieldName
                    fieldName = myField.value();
                }
                if(!"id".equals(fieldName)){
                    String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
                    //通过反射 获取get的方法
                    Method getMethod = aClass.getDeclaredMethod(methodName);
                    Object obj = getMethod.invoke(t);
                    if(null != obj){
                        statement.setObject(++index, obj);
                    }
                }
            }
            statement.setObject(++index, id);
            statement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, statement, connection);
        }
    }
}
